/*
 * These tests are not written to validate the results returned by the native 
 * libraries (these are assumed to be correct), but to test the interface.
 * That is, that the rountine can be located, data can be passed to them,
 * and that a result is returned.
 */

using NUnit.Framework;

namespace dnAnalytics.Nli.UnitTests {
	[TestFixture]
	[Category("LAPACK")]
	[Category("ATLAS")]
	public class ClapackLapackTest : LapackTest {
		public ClapackLapackTest() {
			lapack = Lapack.Provider(LapackProvider.Clapack);
		}
	}

	[TestFixture]
	[Category("LAPACK")]
	[Category("MKL")]
	public class MklLapackTest : LapackTest {
		public MklLapackTest() {
			lapack = Lapack.Provider(LapackProvider.Mkl);
		}
	}

	[TestFixture]
	[Category("LAPACK")]
	[Category("ACML")]
	public class AcmlLapackTest : LapackTest {
		public AcmlLapackTest() {
			lapack = Lapack.Provider(LapackProvider.Acml);
		}
	}

	[TestFixture]
	[Category("LAPACK")]
	[Category("ACMLCVF")]
	public class AcmlCvfLapackTest : LapackTest {
		public AcmlCvfLapackTest() {
			lapack = Lapack.Provider(LapackProvider.AcmlCvf);
		}
	}

	public abstract class LapackTest {
		protected ILapack lapack;
		private const float delta = 1e-4f;

		[Test]
		public void Sgels() {
			float[] a = new float[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			float[] b = new float[] {10, 10, 10, 10, 10, 10, 10, 10, 10};

			lapack.Sgels('N', 3, 3, 3, a, 3, b, 3);
			Assert.AreEqual(5, b[0]);
			Assert.AreEqual(5, b[1]);
			Assert.AreEqual(5, b[2]);
			Assert.AreEqual(5, b[3]);
			Assert.AreEqual(5, b[4]);
			Assert.AreEqual(5, b[5]);
			Assert.AreEqual(5, b[6]);
			Assert.AreEqual(5, b[7]);
			Assert.AreEqual(5, b[8]);
		}

		[Test]
		public void Dgels() {
			double[] a = new double[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			double[] b = new double[] {10, 10, 10, 10, 10, 10, 10, 10, 10};

			lapack.Dgels('N', 3, 3, 3, a, 3, b, 3);
			Assert.AreEqual(5, b[0]);
			Assert.AreEqual(5, b[1]);
			Assert.AreEqual(5, b[2]);
			Assert.AreEqual(5, b[3]);
			Assert.AreEqual(5, b[4]);
			Assert.AreEqual(5, b[5]);
			Assert.AreEqual(5, b[6]);
			Assert.AreEqual(5, b[7]);
			Assert.AreEqual(5, b[8]);
		}

		[Test]
		public void Cgels() {
			ComplexFloat[] a = new ComplexFloat[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			ComplexFloat[] b = new ComplexFloat[] {10, 10, 10, 10, 10, 10, 10, 10, 10};

			lapack.Cgels('N', 3, 3, 3, a, 3, b, 3);
			Assert.AreEqual(5, b[0].Real);
			Assert.AreEqual(5, b[1].Real);
			Assert.AreEqual(5, b[2].Real);
			Assert.AreEqual(5, b[3].Real);
			Assert.AreEqual(5, b[4].Real);
			Assert.AreEqual(5, b[5].Real);
			Assert.AreEqual(5, b[6].Real);
			Assert.AreEqual(5, b[7].Real);
			Assert.AreEqual(5, b[8].Real);
		}

		[Test]
		public void Zgels() {
			ComplexDouble[] a = new ComplexDouble[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			ComplexDouble[] b = new ComplexDouble[] {10, 10, 10, 10, 10, 10, 10, 10, 10};

			lapack.Zgels('N', 3, 3, 3, a, 3, b, 3);
			Assert.AreEqual(5, b[0].Real);
			Assert.AreEqual(5, b[1].Real);
			Assert.AreEqual(5, b[2].Real);
			Assert.AreEqual(5, b[3].Real);
			Assert.AreEqual(5, b[4].Real);
			Assert.AreEqual(5, b[5].Real);
			Assert.AreEqual(5, b[6].Real);
			Assert.AreEqual(5, b[7].Real);
			Assert.AreEqual(5, b[8].Real);
		}

		[Test]
		public void Sgelss() {
			float[] a = new float[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			float[] b = new float[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			float[] s = null;
			int rank = 0;

			lapack.Sgelss(3, 3, 3, a, 3, b, 3, out s, ref rank);
			Assert.AreEqual(5, b[0]);
			Assert.AreEqual(5, b[1]);
			Assert.AreEqual(5, b[2]);
			Assert.AreEqual(5, b[3]);
			Assert.AreEqual(5, b[4]);
			Assert.AreEqual(5, b[5]);
			Assert.AreEqual(5, b[6]);
			Assert.AreEqual(5, b[7]);
			Assert.AreEqual(5, b[8]);
			Assert.AreEqual(3, rank);
			Assert.AreEqual(2, s[0]);
			Assert.AreEqual(2, s[1]);
			Assert.AreEqual(2, s[2]);
		}

		[Test]
		public void Dgelss() {
			double[] a = new double[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			double[] b = new double[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			double[] s = null;
			int rank = 0;

			lapack.Dgelss(3, 3, 3, a, 3, b, 3, out s, ref rank);
			Assert.AreEqual(5, b[0]);
			Assert.AreEqual(5, b[1]);
			Assert.AreEqual(5, b[2]);
			Assert.AreEqual(5, b[3]);
			Assert.AreEqual(5, b[4]);
			Assert.AreEqual(5, b[5]);
			Assert.AreEqual(5, b[6]);
			Assert.AreEqual(5, b[7]);
			Assert.AreEqual(5, b[8]);
			Assert.AreEqual(3, rank);
			Assert.AreEqual(2, s[0]);
			Assert.AreEqual(2, s[1]);
			Assert.AreEqual(2, s[2]);
		}

		[Test]
		public void Cgelss() {
			ComplexFloat[] a = new ComplexFloat[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			ComplexFloat[] b = new ComplexFloat[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			float[] s = null;
			int rank = 0;

			lapack.Cgelss(3, 3, 3, a, 3, b, 3, out s, ref rank);
			Assert.AreEqual(5, b[0].Real);
			Assert.AreEqual(5, b[1].Real);
			Assert.AreEqual(5, b[2].Real);
			Assert.AreEqual(5, b[3].Real);
			Assert.AreEqual(5, b[4].Real);
			Assert.AreEqual(5, b[5].Real);
			Assert.AreEqual(5, b[6].Real);
			Assert.AreEqual(5, b[7].Real);
			Assert.AreEqual(5, b[8].Real);
			Assert.AreEqual(3, rank);
			Assert.AreEqual(2, s[0]);
			Assert.AreEqual(2, s[1]);
			Assert.AreEqual(2, s[2]);
		}

		[Test]
		public void Zgelss() {
			ComplexDouble[] a = new ComplexDouble[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			ComplexDouble[] b = new ComplexDouble[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			double[] s = null;
			int rank = 0;

			lapack.Zgelss(3, 3, 3, a, 3, b, 3, out s, ref rank);
			Assert.AreEqual(5, b[0].Real);
			Assert.AreEqual(5, b[1].Real);
			Assert.AreEqual(5, b[2].Real);
			Assert.AreEqual(5, b[3].Real);
			Assert.AreEqual(5, b[4].Real);
			Assert.AreEqual(5, b[5].Real);
			Assert.AreEqual(5, b[6].Real);
			Assert.AreEqual(5, b[7].Real);
			Assert.AreEqual(5, b[8].Real);
			Assert.AreEqual(3, rank);
			Assert.AreEqual(2, s[0]);
			Assert.AreEqual(2, s[1]);
			Assert.AreEqual(2, s[2]);
		}

		[Test]
		public void Sgelsy() {
			float[] a = new float[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			float[] b = new float[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			int[] jpvt = new int[3];
			int rank = 0;

			lapack.Sgelsy(3, 3, 3, a, 3, b, 3, jpvt, .01f, ref rank);
			Assert.AreEqual(5, b[0]);
			Assert.AreEqual(5, b[1]);
			Assert.AreEqual(5, b[2]);
			Assert.AreEqual(5, b[3]);
			Assert.AreEqual(5, b[4]);
			Assert.AreEqual(5, b[5]);
			Assert.AreEqual(5, b[6]);
			Assert.AreEqual(5, b[7]);
			Assert.AreEqual(5, b[8]);
			Assert.AreEqual(3, rank);
			Assert.AreEqual(1, jpvt[0]);
			Assert.AreEqual(2, jpvt[1]);
			Assert.AreEqual(3, jpvt[2]);
		}

		[Test]
		public void Dgelsy() {
			double[] a = new double[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			double[] b = new double[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			int[] jpvt = new int[3];
			int rank = 0;

			lapack.Dgelsy(3, 3, 3, a, 3, b, 3, jpvt, .01f, ref rank);
			Assert.AreEqual(5, b[0]);
			Assert.AreEqual(5, b[1]);
			Assert.AreEqual(5, b[2]);
			Assert.AreEqual(5, b[3]);
			Assert.AreEqual(5, b[4]);
			Assert.AreEqual(5, b[5]);
			Assert.AreEqual(5, b[6]);
			Assert.AreEqual(5, b[7]);
			Assert.AreEqual(5, b[8]);
			Assert.AreEqual(3, rank);
			Assert.AreEqual(1, jpvt[0]);
			Assert.AreEqual(2, jpvt[1]);
			Assert.AreEqual(3, jpvt[2]);
		}

		[Test]
		public void Cgelsy() {
			ComplexFloat[] a = new ComplexFloat[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			ComplexFloat[] b = new ComplexFloat[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			int[] jpvt = new int[3];
			int rank = 0;
			lapack.Cgelsy(3, 3, 3, a, 3, b, 3, jpvt, .01f, ref rank);
			Assert.AreEqual(5, b[0].Real);
			Assert.AreEqual(5, b[1].Real);
			Assert.AreEqual(5, b[2].Real);
			Assert.AreEqual(5, b[3].Real);
			Assert.AreEqual(5, b[4].Real);
			Assert.AreEqual(5, b[5].Real);
			Assert.AreEqual(5, b[6].Real);
			Assert.AreEqual(5, b[7].Real);
			Assert.AreEqual(5, b[8].Real);
			Assert.AreEqual(3, rank);
			Assert.AreEqual(1, jpvt[0]);
			Assert.AreEqual(2, jpvt[1]);
			Assert.AreEqual(3, jpvt[2]);
		}

		[Test]
		public void Zgelsy() {
			ComplexDouble[] a = new ComplexDouble[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			ComplexDouble[] b = new ComplexDouble[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			int[] jpvt = new int[3];
			int rank = 0;
			lapack.Zgelsy(3, 3, 3, a, 3, b, 3, jpvt, .01f, ref rank);
			Assert.AreEqual(5, b[0].Real);
			Assert.AreEqual(5, b[1].Real);
			Assert.AreEqual(5, b[2].Real);
			Assert.AreEqual(5, b[3].Real);
			Assert.AreEqual(5, b[4].Real);
			Assert.AreEqual(5, b[5].Real);
			Assert.AreEqual(5, b[6].Real);
			Assert.AreEqual(5, b[7].Real);
			Assert.AreEqual(5, b[8].Real);
			Assert.AreEqual(3, rank);
			Assert.AreEqual(1, jpvt[0]);
			Assert.AreEqual(2, jpvt[1]);
			Assert.AreEqual(3, jpvt[2]);
		}

		[Test]
		public void Sgeqp3() {
			float[] a = new float[] {1, 0, 0, 0, 2, 0, 0, 0, 2};
			int[] jpvt = new int[3];
			float[] tau = new float[3];

			lapack.Sgeqp3(3, 3, a, 3, jpvt, tau);
			Assert.AreEqual(-2, a[0]);
			Assert.AreEqual(1, a[1]);
			Assert.AreEqual(0, a[2]);
			Assert.AreEqual(0, a[3]);
			Assert.AreEqual(-2, a[4]);
			Assert.AreEqual(1, a[5]);
			Assert.AreEqual(0, a[6]);
			Assert.AreEqual(0, a[7]);
			Assert.AreEqual(1, a[8]);
			Assert.AreEqual(2, jpvt[0]);
			Assert.AreEqual(3, jpvt[1]);
			Assert.AreEqual(1, jpvt[2]);
			Assert.AreEqual(1, tau[0]);
			Assert.AreEqual(1, tau[1]);
			Assert.AreEqual(0, tau[2]);
		}

		[Test]
		public void Dgeqp3() {
			double[] a = new double[] {1, 0, 0, 0, 2, 0, 0, 0, 2};
			int[] jpvt = new int[3];
			double[] tau = new double[3];

			lapack.Dgeqp3(3, 3, a, 3, jpvt, tau);
			Assert.AreEqual(-2, a[0]);
			Assert.AreEqual(1, a[1]);
			Assert.AreEqual(0, a[2]);
			Assert.AreEqual(0, a[3]);
			Assert.AreEqual(-2, a[4]);
			Assert.AreEqual(1, a[5]);
			Assert.AreEqual(0, a[6]);
			Assert.AreEqual(0, a[7]);
			Assert.AreEqual(1, a[8]);
			Assert.AreEqual(2, jpvt[0]);
			Assert.AreEqual(3, jpvt[1]);
			Assert.AreEqual(1, jpvt[2]);
			Assert.AreEqual(1, tau[0]);
			Assert.AreEqual(1, tau[1]);
			Assert.AreEqual(0, tau[2]);
		}

		[Test]
		public void Cgeqp3() {
			ComplexFloat[] a = new ComplexFloat[] {1, 0, 0, 0, 2, 0, 0, 0, 2};
			int[] jpvt = new int[3];
			ComplexFloat[] tau = new ComplexFloat[3];

			lapack.Cgeqp3(3, 3, a, 3, jpvt, tau);
			Assert.AreEqual(-2, a[0].Real);
			Assert.AreEqual(1, a[1].Real);
			Assert.AreEqual(0, a[2].Real);
			Assert.AreEqual(0, a[3].Real);
			Assert.AreEqual(-2, a[4].Real);
			Assert.AreEqual(1, a[5].Real);
			Assert.AreEqual(0, a[6].Real);
			Assert.AreEqual(0, a[7].Real);
			Assert.AreEqual(1, a[8].Real);
			Assert.AreEqual(2, jpvt[0]);
			Assert.AreEqual(3, jpvt[1]);
			Assert.AreEqual(1, jpvt[2]);
			Assert.AreEqual(1, tau[0].Real);
			Assert.AreEqual(1, tau[1].Real);
			Assert.AreEqual(0, tau[2].Real);
		}

		[Test]
		public void Zgeqp3() {
			ComplexDouble[] a = new ComplexDouble[] {1, 0, 0, 0, 2, 0, 0, 0, 2};
			int[] jpvt = new int[3];
			ComplexDouble[] tau = new ComplexDouble[3];

			lapack.Zgeqp3(3, 3, a, 3, jpvt, tau);
			Assert.AreEqual(-2, a[0].Real);
			Assert.AreEqual(1, a[1].Real);
			Assert.AreEqual(0, a[2].Real);
			Assert.AreEqual(0, a[3].Real);
			Assert.AreEqual(-2, a[4].Real);
			Assert.AreEqual(1, a[5].Real);
			Assert.AreEqual(0, a[6].Real);
			Assert.AreEqual(0, a[7].Real);
			Assert.AreEqual(1, a[8].Real);
			Assert.AreEqual(2, jpvt[0]);
			Assert.AreEqual(3, jpvt[1]);
			Assert.AreEqual(1, jpvt[2]);
			Assert.AreEqual(1, tau[0].Real);
			Assert.AreEqual(1, tau[1].Real);
		}

		[Test]
		public void Sgesvd() {
			float[] a = new float[] {0, 0, 0, 1, 1, 1, 2, 2, 2};
			float[] s = new float[3];
			float[] u = new float[9];
			float[] vt = new float[9];

			lapack.Sgesvd('A', 'A', 3, 3, a, 3, s, u, 3, vt, 3);
			Assert.AreEqual(3.872983, s[0], delta);
			Assert.AreEqual(0, s[1], delta);
			Assert.AreEqual(0, s[2], delta);
		}

		[Test]
		public void Dgesvd() {
			double[] a = new double[] {0, 0, 0, 1, 1, 1, 2, 2, 2};
			double[] s = new double[3];
			double[] u = new double[9];
			double[] vt = new double[9];

			lapack.Dgesvd('A', 'A', 3, 3, a, 3, s, u, 3, vt, 3);
			Assert.AreEqual(3.872983, s[0], delta);
			Assert.AreEqual(0, s[1], delta);
			Assert.AreEqual(0, s[2], delta);
		}

		[Test]
		public void Cgesvd() {
			ComplexFloat[] a = new ComplexFloat[] {0, 0, 0, 1, 1, 1, 2, 2, 2};
			float[] s = new float[3];
			ComplexFloat[] u = new ComplexFloat[9];
			ComplexFloat[] vt = new ComplexFloat[9];

			lapack.Cgesvd('A', 'A', 3, 3, a, 3, s, u, 3, vt, 3);
			Assert.AreEqual(3.872983, s[0], delta);
			Assert.AreEqual(0, s[1], delta);
			Assert.AreEqual(0, s[2], delta);
		}

		[Test]
		public void Zgesvd() {
			ComplexDouble[] a = new ComplexDouble[] {1, 1, 1, 1, 1, 1, 2, 2, 2};
			double[] s = new double[3];
			ComplexDouble[] u = new ComplexDouble[9];
			ComplexDouble[] vt = new ComplexDouble[9];
			lapack.Zgesvd('A', 'A', 3, 3, a, 3, s, u, 3, vt, 3);
			Assert.AreEqual(4.242640, s[0], delta);
			Assert.AreEqual(0, s[1], delta);
			Assert.AreEqual(0, s[2], delta);
		}

		[Test]
		public void Sgetrf() {
			float[] a = new float[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] ipiv;

			lapack.Sgetrf(3, 3, a, 3, out ipiv);

			Assert.AreEqual(3, a[0], delta);
			Assert.AreEqual(.3333, a[1], delta);
			Assert.AreEqual(.6667, a[2], delta);
			Assert.AreEqual(6, a[3], delta);
			Assert.AreEqual(2, a[4], delta);
			Assert.AreEqual(.5, a[5], delta);
			Assert.AreEqual(9, a[6], delta);
			Assert.AreEqual(4, a[7], delta);
			Assert.AreEqual(0, a[8], delta);
			Assert.AreEqual(3, ipiv[0]);
			Assert.AreEqual(3, ipiv[1]);
			Assert.AreEqual(3, ipiv[2]);
		}

		[Test]
		public void Dgetrf() {
			double[] a = new double[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] ipiv;

			lapack.Dgetrf(3, 3, a, 3, out ipiv);

			Assert.AreEqual(3, a[0], delta);
			Assert.AreEqual(.3333, a[1], delta);
			Assert.AreEqual(.6667, a[2], delta);
			Assert.AreEqual(6, a[3], delta);
			Assert.AreEqual(2, a[4], delta);
			Assert.AreEqual(.5, a[5], delta);
			Assert.AreEqual(9, a[6], delta);
			Assert.AreEqual(4, a[7], delta);
			Assert.AreEqual(0, a[8], delta);
		}

		[Test]
		public void Cgetrf() {
			ComplexFloat[] a = new ComplexFloat[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] ipiv;

			lapack.Cgetrf(3, 3, a, 3, out ipiv);

			Assert.AreEqual(3, a[0].Real, delta);
			Assert.AreEqual(.3333, a[1].Real, delta);
			Assert.AreEqual(.6667, a[2].Real, delta);
			Assert.AreEqual(6, a[3].Real, delta);
			Assert.AreEqual(2, a[4].Real, delta);
			Assert.AreEqual(.5, a[5].Real, delta);
			Assert.AreEqual(9, a[6].Real, delta);
			Assert.AreEqual(4, a[7].Real, delta);
			Assert.AreEqual(0, a[8].Real, delta);
		}

		[Test]
		public void Zgetrf() {
			ComplexDouble[] a = new ComplexDouble[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] ipiv;

			lapack.Zgetrf(3, 3, a, 3, out ipiv);

			Assert.AreEqual(3, a[0].Real, delta);
			Assert.AreEqual(.3333, a[1].Real, delta);
			Assert.AreEqual(.6667, a[2].Real, delta);
			Assert.AreEqual(6, a[3].Real, delta);
			Assert.AreEqual(2, a[4].Real, delta);
			Assert.AreEqual(.5, a[5].Real, delta);
			Assert.AreEqual(9, a[6].Real, delta);
			Assert.AreEqual(4, a[7].Real, delta);
			Assert.AreEqual(0, a[8].Real, delta);
		}

		[Test]
		public void Sgetri() {
			float[] a = new float[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] ipiv = new int[] {3, 3, 3};

			lapack.Sgetri(3, a, 3, ipiv);

			Assert.AreEqual(-.4, a[0], delta);
			Assert.AreEqual(1.2667, a[1], delta);
			Assert.AreEqual(-.6667, a[2], delta);
			Assert.AreEqual(-.0667, a[3], delta);
			Assert.AreEqual(-.1778, a[4], delta);
			Assert.AreEqual(.1111, a[5], delta);
			Assert.AreEqual(2, a[6], delta);
			Assert.AreEqual(-2, a[7], delta);
			Assert.AreEqual(1, a[8], delta);
		}

		[Test]
		public void Dgetri() {
			double[] a = new double[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] ipiv = new int[] {3, 3, 3};

			lapack.Dgetri(3, a, 3, ipiv);

			Assert.AreEqual(-.4, a[0], delta);
			Assert.AreEqual(1.2667, a[1], delta);
			Assert.AreEqual(-.6667, a[2], delta);
			Assert.AreEqual(-.0667, a[3], delta);
			Assert.AreEqual(-.1778, a[4], delta);
			Assert.AreEqual(.1111, a[5], delta);
			Assert.AreEqual(2, a[6], delta);
			Assert.AreEqual(-2, a[7], delta);
			Assert.AreEqual(1, a[8], delta);
		}

		[Test]
		public void Cgetri() {
			ComplexFloat[] a = new ComplexFloat[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] ipiv = new int[] {3, 3, 3};

			lapack.Cgetri(3, a, 3, ipiv);

			Assert.AreEqual(-.4, a[0].Real, delta);
			Assert.AreEqual(1.2667, a[1].Real, delta);
			Assert.AreEqual(-.6667, a[2].Real, delta);
			Assert.AreEqual(-.0667, a[3].Real, delta);
			Assert.AreEqual(-.1778, a[4].Real, delta);
			Assert.AreEqual(.1111, a[5].Real, delta);
			Assert.AreEqual(2, a[6].Real, delta);
			Assert.AreEqual(-2, a[7].Real, delta);
			Assert.AreEqual(1, a[8].Real, delta);
		}

		[Test]
		public void Zgetri() {
			ComplexDouble[] a = new ComplexDouble[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] ipiv = new int[] {3, 3, 3};

			lapack.Zgetri(3, a, 3, ipiv);

			Assert.AreEqual(-.4, a[0].Real, delta);
			Assert.AreEqual(1.2667, a[1].Real, delta);
			Assert.AreEqual(-.6667, a[2].Real, delta);
			Assert.AreEqual(-.0667, a[3].Real, delta);
			Assert.AreEqual(-.1778, a[4].Real, delta);
			Assert.AreEqual(.1111, a[5].Real, delta);
			Assert.AreEqual(2, a[6].Real, delta);
			Assert.AreEqual(-2, a[7].Real, delta);
			Assert.AreEqual(1, a[8].Real, delta);
		}

		[Test]
		public void Sgetrs() {
			float[] a = new float[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			float[] b = new float[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			int[] ipiv = {1, 2, 3};

			lapack.Sgetrs('N', 3, 3, a, 3, ipiv, b, 3);
			Assert.AreEqual(5, b[0]);
			Assert.AreEqual(5, b[1]);
			Assert.AreEqual(5, b[2]);
			Assert.AreEqual(5, b[3]);
			Assert.AreEqual(5, b[4]);
			Assert.AreEqual(5, b[5]);
			Assert.AreEqual(5, b[6]);
			Assert.AreEqual(5, b[7]);
			Assert.AreEqual(5, b[8]);
		}

		[Test]
		public void Dgetrs() {
			double[] a = new double[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			double[] b = new double[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			int[] ipiv = {1, 2, 3};

			lapack.Dgetrs('N', 3, 3, a, 3, ipiv, b, 3);
			Assert.AreEqual(5, b[0]);
			Assert.AreEqual(5, b[1]);
			Assert.AreEqual(5, b[2]);
			Assert.AreEqual(5, b[3]);
			Assert.AreEqual(5, b[4]);
			Assert.AreEqual(5, b[5]);
			Assert.AreEqual(5, b[6]);
			Assert.AreEqual(5, b[7]);
			Assert.AreEqual(5, b[8]);
		}

		[Test]
		public void Cgetrs() {
			ComplexFloat[] a = new ComplexFloat[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			ComplexFloat[] b = new ComplexFloat[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			int[] ipiv = {1, 2, 3};

			lapack.Cgetrs('N', 3, 3, a, 3, ipiv, b, 3);
			Assert.AreEqual(5, b[0].Real);
			Assert.AreEqual(5, b[1].Real);
			Assert.AreEqual(5, b[2].Real);
			Assert.AreEqual(5, b[3].Real);
			Assert.AreEqual(5, b[4].Real);
			Assert.AreEqual(5, b[5].Real);
			Assert.AreEqual(5, b[6].Real);
			Assert.AreEqual(5, b[7].Real);
			Assert.AreEqual(5, b[8].Real);
		}

		[Test]
		public void Zgetrs() {
			ComplexDouble[] a = new ComplexDouble[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			ComplexDouble[] b = new ComplexDouble[] {10, 10, 10, 10, 10, 10, 10, 10, 10};
			int[] ipiv = {1, 2, 3};

			lapack.Zgetrs('N', 3, 3, a, 3, ipiv, b, 3);
			Assert.AreEqual(5, b[0].Real);
			Assert.AreEqual(5, b[1].Real);
			Assert.AreEqual(5, b[2].Real);
			Assert.AreEqual(5, b[3].Real);
			Assert.AreEqual(5, b[4].Real);
			Assert.AreEqual(5, b[5].Real);
			Assert.AreEqual(5, b[6].Real);
			Assert.AreEqual(5, b[7].Real);
			Assert.AreEqual(5, b[8].Real);
		}

		[Test]
		public void Sorgqr() {
			float[] a = new float[] {1, 0, 0, 0, 2, 0, 0, 0, 2};
			int[] jpvt = new int[3];
			float[] tau = new float[3];

			lapack.Sgeqp3(3, 3, a, 3, jpvt, tau);
			lapack.Sorgqr(3, 3, 3, a, 3, tau);
			Assert.AreEqual(0, a[0]);
			Assert.AreEqual(-1, a[1]);
			Assert.AreEqual(0, a[2]);
			Assert.AreEqual(0, a[3]);
			Assert.AreEqual(0, a[4]);
			Assert.AreEqual(-1, a[5]);
			Assert.AreEqual(1, a[6]);
			Assert.AreEqual(0, a[7]);
			Assert.AreEqual(0, a[8]);
		}

		[Test]
		public void Dorgqr() {
			double[] a = new double[] {1, 0, 0, 0, 2, 0, 0, 0, 2};
			int[] jpvt = new int[3];
			double[] tau = new double[3];

			lapack.Dgeqp3(3, 3, a, 3, jpvt, tau);
			lapack.Dorgqr(3, 3, 3, a, 3, tau);
			Assert.AreEqual(0, a[0]);
			Assert.AreEqual(-1, a[1]);
			Assert.AreEqual(0, a[2]);
			Assert.AreEqual(0, a[3]);
			Assert.AreEqual(0, a[4]);
			Assert.AreEqual(-1, a[5]);
			Assert.AreEqual(1, a[6]);
			Assert.AreEqual(0, a[7]);
			Assert.AreEqual(0, a[8]);
		}

		[Test]
		public void Sormqr() {
			float[] a = new float[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			float[] c = new float[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] jpvt = new int[3];
			float[] tau = new float[3];

			lapack.Sgeqp3(3, 3, a, 3, jpvt, tau);
			lapack.Sormqr('R', 'T', 3, 3, 3, a, 3, tau, c, 3);

			Assert.AreEqual(5.4034, c[0], delta);
			Assert.AreEqual(6.0712, c[1], delta);
			Assert.AreEqual(6.7389, c[2], delta);
			Assert.AreEqual(-6.0553, c[3], delta);
			Assert.AreEqual(-7.3876, c[4], delta);
			Assert.AreEqual(-8.7198, c[5], delta);
			Assert.AreEqual(-0.36775, c[6], delta);
			Assert.AreEqual(-1.2504, c[7], delta);
			Assert.AreEqual(-2.1332, c[8], delta);
		}

		[Test]
		public void Dormqr() {
			double[] a = new double[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			double[] c = new double[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] jpvt = new int[3];
			double[] tau = new double[3];

			lapack.Dgeqp3(3, 3, a, 3, jpvt, tau);
			lapack.Dormqr('R', 'T', 3, 3, 3, a, 3, tau, c, 3);

			Assert.AreEqual(5.4034, c[0], delta);
			Assert.AreEqual(6.0712, c[1], delta);
			Assert.AreEqual(6.7389, c[2], delta);
			Assert.AreEqual(-6.0553, c[3], delta);
			Assert.AreEqual(-7.3876, c[4], delta);
			Assert.AreEqual(-8.7198, c[5], delta);
			Assert.AreEqual(-0.36775, c[6], delta);
			Assert.AreEqual(-1.2504, c[7], delta);
			Assert.AreEqual(-2.1332, c[8], delta);
		}

		[Test]
		public void Cungqr() {
			ComplexFloat[] a = new ComplexFloat[] {1, 0, 0, 0, 2, 0, 0, 0, 2};
			int[] jpvt = new int[3];
			ComplexFloat[] tau = new ComplexFloat[3];

			lapack.Cgeqp3(3, 3, a, 3, jpvt, tau);
			lapack.Cungqr(3, 3, 3, a, 3, tau);
			Assert.AreEqual(0, a[0].Real);
			Assert.AreEqual(-1, a[1].Real);
			Assert.AreEqual(0, a[2].Real);
			Assert.AreEqual(0, a[3].Real);
			Assert.AreEqual(0, a[4].Real);
			Assert.AreEqual(-1, a[5].Real);
			Assert.AreEqual(1, a[6].Real);
			Assert.AreEqual(0, a[7].Real);
			Assert.AreEqual(0, a[8].Real);
		}

		[Test]
		public void Zungqr() {
			ComplexDouble[] a = new ComplexDouble[] {1, 0, 0, 0, 2, 0, 0, 0, 2};
			int[] jpvt = new int[3];
			ComplexDouble[] tau = new ComplexDouble[3];

			lapack.Zgeqp3(3, 3, a, 3, jpvt, tau);
			lapack.Zungqr(3, 3, 3, a, 3, tau);
			Assert.AreEqual(0, a[0].Real);
			Assert.AreEqual(-1, a[1].Real);
			Assert.AreEqual(0, a[2].Real);
			Assert.AreEqual(0, a[3].Real);
			Assert.AreEqual(0, a[4].Real);
			Assert.AreEqual(-1, a[5].Real);
			Assert.AreEqual(1, a[6].Real);
			Assert.AreEqual(0, a[7].Real);
			Assert.AreEqual(0, a[8].Real);
		}

		[Test]
		public void Cunmqr() {
			ComplexFloat[] a = new ComplexFloat[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			ComplexFloat[] c = new ComplexFloat[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] jpvt = new int[3];
			ComplexFloat[] tau = new ComplexFloat[3];

			lapack.Cgeqp3(3, 3, a, 3, jpvt, tau);
			lapack.Cunmqr('R', 'C', 3, 3, 3, a, 3, tau, c, 3);

			Assert.AreEqual(5.4034, c[0].Real, delta);
			Assert.AreEqual(6.0712, c[1].Real, delta);
			Assert.AreEqual(6.7389, c[2].Real, delta);
			Assert.AreEqual(-6.0553, c[3].Real, delta);
			Assert.AreEqual(-7.3876, c[4].Real, delta);
			Assert.AreEqual(-8.7198, c[5].Real, delta);
			Assert.AreEqual(-0.36775, c[6].Real, delta);
			Assert.AreEqual(-1.2504, c[7].Real, delta);
			Assert.AreEqual(-2.1332, c[8].Real, delta);
		}

		[Test]
		public void Zunmqr() {
			ComplexDouble[] a = new ComplexDouble[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			ComplexDouble[] c = new ComplexDouble[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
			int[] jpvt = new int[3];
			ComplexDouble[] tau = new ComplexDouble[3];

			lapack.Zgeqp3(3, 3, a, 3, jpvt, tau);
			lapack.Zunmqr('R', 'C', 3, 3, 3, a, 3, tau, c, 3);

			Assert.AreEqual(5.4034, c[0].Real, delta);
			Assert.AreEqual(6.0712, c[1].Real, delta);
			Assert.AreEqual(6.7389, c[2].Real, delta);
			Assert.AreEqual(-6.0553, c[3].Real, delta);
			Assert.AreEqual(-7.3876, c[4].Real, delta);
			Assert.AreEqual(-8.7198, c[5].Real, delta);
			Assert.AreEqual(-0.36775, c[6].Real, delta);
			Assert.AreEqual(-1.2504, c[7].Real, delta);
			Assert.AreEqual(-2.1332, c[8].Real, delta);
		}

		[Test]
		public void Spotrf() {
			float[] a = new float[] {1, 2, 3, 0, 4, 5, 0, 0, 6};

			lapack.Spotrf('U', 3, a, 3);
			Assert.AreEqual(1, a[0], delta);
			Assert.AreEqual(2, a[1], delta);
			Assert.AreEqual(3, a[2], delta);
			Assert.AreEqual(0, a[3], delta);
			Assert.AreEqual(2, a[4], delta);
			Assert.AreEqual(5, a[5], delta);
			Assert.AreEqual(0, a[6], delta);
			Assert.AreEqual(0, a[7], delta);
			Assert.AreEqual(2.4494, a[8], delta);
		}

		[Test]
		public void Dpotrf() {
			double[] a = new double[] {1, 2, 3, 0, 4, 5, 0, 0, 6};

			lapack.Dpotrf('U', 3, a, 3);
			Assert.AreEqual(1, a[0], delta);
			Assert.AreEqual(2, a[1], delta);
			Assert.AreEqual(3, a[2], delta);
			Assert.AreEqual(0, a[3], delta);
			Assert.AreEqual(2, a[4], delta);
			Assert.AreEqual(5, a[5], delta);
			Assert.AreEqual(0, a[6], delta);
			Assert.AreEqual(0, a[7], delta);
			Assert.AreEqual(2.4494, a[8], delta);
		}

		[Test]
		public void Cpotrf() {
			ComplexFloat[] a = new ComplexFloat[] {1, 2, 3, 0, 4, 5, 0, 0, 6};

			lapack.Cpotrf('U', 3, a, 3);
			Assert.AreEqual(1, a[0].Real, delta);
			Assert.AreEqual(2, a[1].Real, delta);
			Assert.AreEqual(3, a[2].Real, delta);
			Assert.AreEqual(0, a[3].Real, delta);
			Assert.AreEqual(2, a[4].Real, delta);
			Assert.AreEqual(5, a[5].Real, delta);
			Assert.AreEqual(0, a[6].Real, delta);
			Assert.AreEqual(0, a[7].Real, delta);
			Assert.AreEqual(2.4494, a[8].Real, delta);
		}

		[Test]
		public void Zpotrf() {
			ComplexDouble[] a = new ComplexDouble[] {1, 2, 3, 0, 4, 5, 0, 0, 6};

			lapack.Zpotrf('U', 3, a, 3);
			Assert.AreEqual(1, a[0].Real, delta);
			Assert.AreEqual(2, a[1].Real, delta);
			Assert.AreEqual(3, a[2].Real, delta);
			Assert.AreEqual(0, a[3].Real, delta);
			Assert.AreEqual(2, a[4].Real, delta);
			Assert.AreEqual(5, a[5].Real, delta);
			Assert.AreEqual(0, a[6].Real, delta);
			Assert.AreEqual(0, a[7].Real, delta);
			Assert.AreEqual(2.4494, a[8].Real, delta);
		}

		[Test]
		public void Spotri() {
			float[] a = new float[] {1, 2, 3, 0, 4, 5, 0, 0, 6};

			lapack.Spotrf('U', 3, a, 3);
			lapack.Spotri('U', 3, a, 3);

			Assert.AreEqual(1, a[0], delta);
			Assert.AreEqual(2, a[1], delta);
			Assert.AreEqual(3, a[2], delta);
			Assert.AreEqual(0, a[3], delta);
			Assert.AreEqual(.25, a[4], delta);
			Assert.AreEqual(5, a[5], delta);
			Assert.AreEqual(0, a[6], delta);
			Assert.AreEqual(0, a[7], delta);
			Assert.AreEqual(0.1667, a[8], delta);
		}

		[Test]
		public void Dpotri() {
			double[] a = new double[] {1, 2, 3, 0, 4, 5, 0, 0, 6};

			lapack.Dpotrf('U', 3, a, 3);
			lapack.Dpotri('U', 3, a, 3);

			Assert.AreEqual(1, a[0], delta);
			Assert.AreEqual(2, a[1], delta);
			Assert.AreEqual(3, a[2], delta);
			Assert.AreEqual(0, a[3], delta);
			Assert.AreEqual(.25, a[4], delta);
			Assert.AreEqual(5, a[5], delta);
			Assert.AreEqual(0, a[6], delta);
			Assert.AreEqual(0, a[7], delta);
			Assert.AreEqual(0.1667, a[8], delta);
		}

		[Test]
		public void Cpotri() {
			ComplexFloat[] a = new ComplexFloat[] {1, 2, 3, 0, 4, 5, 0, 0, 6};

			lapack.Cpotrf('U', 3, a, 3);
			lapack.Cpotri('U', 3, a, 3);

			Assert.AreEqual(1, a[0].Real, delta);
			Assert.AreEqual(2, a[1].Real, delta);
			Assert.AreEqual(3, a[2].Real, delta);
			Assert.AreEqual(0, a[3].Real, delta);
			Assert.AreEqual(.25, a[4].Real, delta);
			Assert.AreEqual(5, a[5].Real, delta);
			Assert.AreEqual(0, a[6].Real, delta);
			Assert.AreEqual(0, a[7].Real, delta);
			Assert.AreEqual(0.1667, a[8].Real, delta);
		}


		[Test]
		public void Zpotri() {
			ComplexDouble[] a = new ComplexDouble[] {1, 2, 3, 0, 4, 5, 0, 0, 6};

			lapack.Zpotrf('U', 3, a, 3);
			lapack.Zpotri('U', 3, a, 3);

			Assert.AreEqual(1, a[0].Real, delta);
			Assert.AreEqual(2, a[1].Real, delta);
			Assert.AreEqual(3, a[2].Real, delta);
			Assert.AreEqual(0, a[3].Real, delta);
			Assert.AreEqual(.25, a[4].Real, delta);
			Assert.AreEqual(5, a[5].Real, delta);
			Assert.AreEqual(0, a[6].Real, delta);
			Assert.AreEqual(0, a[7].Real, delta);
			Assert.AreEqual(0.1667, a[8].Real, delta);
		}

		[Test]
		public void Spotrs() {
			float[] a = new float[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			float[] b = new float[] {10, 10, 10, 10, 10, 10, 10, 10, 10};

			lapack.Spotrf('U', 3, a, 3);
			lapack.Spotrs('U', 3, 3, a, 3, b, 3);

			Assert.AreEqual(5, b[0], delta);
			Assert.AreEqual(5, b[1], delta);
			Assert.AreEqual(5, b[2], delta);
			Assert.AreEqual(5, b[3], delta);
			Assert.AreEqual(5, b[4], delta);
			Assert.AreEqual(5, b[5], delta);
			Assert.AreEqual(5, b[6], delta);
			Assert.AreEqual(5, b[7], delta);
			Assert.AreEqual(5, b[8], delta);
		}

		[Test]
		public void Dpotrs() {
			double[] a = new double[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			double[] b = new double[] {10, 10, 10, 10, 10, 10, 10, 10, 10};

			lapack.Dpotrf('U', 3, a, 3);
			lapack.Dpotrs('U', 3, 3, a, 3, b, 3);

			Assert.AreEqual(5, b[0], delta);
			Assert.AreEqual(5, b[1], delta);
			Assert.AreEqual(5, b[2], delta);
			Assert.AreEqual(5, b[3], delta);
			Assert.AreEqual(5, b[4], delta);
			Assert.AreEqual(5, b[5], delta);
			Assert.AreEqual(5, b[6], delta);
			Assert.AreEqual(5, b[7], delta);
			Assert.AreEqual(5, b[8], delta);
		}

		[Test]
		public void Cpotrs() {
			ComplexFloat[] a = new ComplexFloat[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			ComplexFloat[] b = new ComplexFloat[] {10, 10, 10, 10, 10, 10, 10, 10, 10};

			lapack.Cpotrf('U', 3, a, 3);
			lapack.Cpotrs('U', 3, 3, a, 3, b, 3);

			Assert.AreEqual(5, b[0].Real, delta);
			Assert.AreEqual(5, b[1].Real, delta);
			Assert.AreEqual(5, b[2].Real, delta);
			Assert.AreEqual(5, b[3].Real, delta);
			Assert.AreEqual(5, b[4].Real, delta);
			Assert.AreEqual(5, b[5].Real, delta);
			Assert.AreEqual(5, b[6].Real, delta);
			Assert.AreEqual(5, b[7].Real, delta);
			Assert.AreEqual(5, b[8].Real, delta);
		}

		[Test]
		public void Zpotrs() {
			ComplexDouble[] a = new ComplexDouble[] {2, 0, 0, 0, 2, 0, 0, 0, 2};
			ComplexDouble[] b = new ComplexDouble[] {10, 10, 10, 10, 10, 10, 10, 10, 10};

			lapack.Zpotrf('U', 3, a, 3);
			lapack.Zpotrs('U', 3, 3, a, 3, b, 3);

			Assert.AreEqual(5, b[0].Real, delta);
			Assert.AreEqual(5, b[1].Real, delta);
			Assert.AreEqual(5, b[2].Real, delta);
			Assert.AreEqual(5, b[3].Real, delta);
			Assert.AreEqual(5, b[4].Real, delta);
			Assert.AreEqual(5, b[5].Real, delta);
			Assert.AreEqual(5, b[6].Real, delta);
			Assert.AreEqual(5, b[7].Real, delta);
			Assert.AreEqual(5, b[8].Real, delta);
		}

		[Test]
		public void Sgecon() {
			float[] a = new float[] {12.3f, 45.6f, 78.39f, 01.2f, 34.5f, 67.8f, 90.1f, 23.4f, 56.7f};
			int[] ipiv;
			float rcond = 5;
			float norm = lapack.Slange('1', 3, 3, a, 3);
			lapack.Sgetrf(3, 3, a, 3, out ipiv);
			lapack.Sgecon('1', 3, a, 3, norm, ref rcond);
			Assert.AreEqual(0.01722, rcond, delta);
		}

		[Test]
		public void Dgecon() {
			double[] a = new double[] {12.3, 45.6, 78.39, 01.2, 34.5, 67.8, 90.1, 23.4, 56.7};
			int[] ipiv;
			double rcond = 5;
			double norm = lapack.Dlange('1', 3, 3, a, 3);
			lapack.Dgetrf(3, 3, a, 3, out ipiv);
			lapack.Dgecon('1', 3, a, 3, norm, ref rcond);
			Assert.AreEqual(0.01722, rcond, delta);
		}

		[Test]
		public void Cgecon() {
			ComplexFloat[] a = new ComplexFloat[] {12.3f, 45.6f, 78.39f, 01.2f, 34.5f, 67.8f, 90.1f, 23.4f, 56.7f};
			int[] ipiv;
			float rcond = 5;
			float norm = lapack.Clange('1', 3, 3, a, 3);
			lapack.Cgetrf(3, 3, a, 3, out ipiv);
			lapack.Cgecon('1', 3, a, 3, norm, ref rcond);
			Assert.AreEqual(0.01722, rcond, delta);
		}

		[Test]
		public void Zgecon() {
			ComplexDouble[] a = new ComplexDouble[] {12.3, 45.6, 78.39, 01.2, 34.5, 67.8, 90.1, 23.4, 56.7};
			int[] ipiv;
			double rcond = 5;
			double norm = lapack.Zlange('1', 3, 3, a, 3);
			lapack.Zgetrf(3, 3, a, 3, out ipiv);
			lapack.Zgecon('1', 3, a, 3, norm, ref rcond);
			Assert.AreEqual(0.01722, rcond, delta);
		}
	}
}